package cn.itsource.ymcc.mq;

import cn.itsource.ymcc.constants.BaseConstants;
import cn.itsource.ymcc.domain.CourseOrder;
import cn.itsource.ymcc.dto.PlaceOrderDto;
import cn.itsource.ymcc.service.ICourseOrderService;
import cn.itsource.ymcc.to.PlaceCourseOrderTo;
import cn.itsource.ymcc.util.AssertUtil;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
//订单事务组
@RocketMQTransactionListener(txProducerGroup = BaseConstants.OrderMQ.TX_ORDER_GROUP)
@Slf4j
public class PlaceOrderTransactionListener implements RocketMQLocalTransactionListener {

    @Autowired
    private ICourseOrderService courseOrderService;

    //执行本地事务
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {

        try{
            log.info("保存订单到MQ，{}，{}",msg,arg);

            AssertUtil.isNotNull(arg,"无效的订单数据");

            //获取主业务传递过来的参数
            Map<String,String> args = (Map<String, String>) arg;
            String SaveOrder = args.get("SaveOrder");

            AssertUtil.isNotEmpty(SaveOrder,"无效的SaveOrder参数");

            //是否可用下单
            if(SaveOrder.equals("true")){
                //多个事务消息，只有第一个消息才保持订单，防止重复下单
                byte[] payload = (byte[]) msg.getPayload();

                String json = new String(payload, "utf-8");
                log.info("保存订单，执行本地事务.{}",json);
                PlaceCourseOrderTo placeCourseOrderTo = JSON.parseObject(json, PlaceCourseOrderTo.class);

                //幂等处理，防止重复下单，如果是集群，要做分布式锁
                synchronized (placeCourseOrderTo.getOrderNo()){
                    if(courseOrderService.selectByOrderNo(placeCourseOrderTo.getOrderNo()) == null){
                        //保存订单到数据库
                        courseOrderService.saveOrder(placeCourseOrderTo);
                    }
                }
            }
            //消息推送，直接返回TRUE
            return RocketMQLocalTransactionState.COMMIT;
        }catch (Exception e){
            e.printStackTrace();
        }

        return RocketMQLocalTransactionState.ROLLBACK;
    }

    //检查本地事务状态
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
        byte[] payload = (byte[]) msg.getPayload();
        try{
            String json = new String(payload, "utf-8");
            log.info("保存订单，回查本地事务.{}",json);

            PlaceCourseOrderTo placeCourseOrderTo = JSON.parseObject(json, PlaceCourseOrderTo.class);

            CourseOrder order = courseOrderService.selectByOrderNo(placeCourseOrderTo.getOrderNo());
            //回查订单状态
            if(order != null && order.getStatusOrder() == BaseConstants.Order.STATUS_APPLY){
                return RocketMQLocalTransactionState.COMMIT;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return RocketMQLocalTransactionState.ROLLBACK;
    }
}
